<!DOCTYPE html>
<html lang="zh-Hans">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 3.8.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"yoursite.com","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="A Quiet Departure.">
<meta property="og:type" content="website">
<meta property="og:title" content="Feng&#39;s Blog">
<meta property="og:url" content="http://yoursite.com/page/11/index.html">
<meta property="og:site_name" content="Feng&#39;s Blog">
<meta property="og:description" content="A Quiet Departure.">
<meta property="og:locale" content="zh-Hans">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Feng&#39;s Blog">
<meta name="twitter:description" content="A Quiet Departure.">

<link rel="canonical" href="http://yoursite.com/page/11/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false,
    lang   : 'zh-Hans'
  };
</script>

  <title>Feng's Blog</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="Toggle navigation bar">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">Feng's Blog</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>Home</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>About</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>Tags</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>Categories</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>Archives</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content index posts-expand">
            
      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-Hans">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2019/10/15/Spring系列之SpringSecurity/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="Fengorz">
      <meta itemprop="description" content="A Quiet Departure.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Feng's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2019/10/15/Spring系列之SpringSecurity/" class="post-title-link" itemprop="url">Spring系列之SpringSecurity</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">Posted on</span>

              <time title="Created: 2019-10-15 21:23:15" itemprop="dateCreated datePublished" datetime="2019-10-15T21:23:15+08:00">2019-10-15</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">Edited on</span>
                <time title="Modified: 2020-07-21 16:49:58" itemprop="dateModified" datetime="2020-07-21T16:49:58+08:00">2020-07-21</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">In</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Spring/" itemprop="url" rel="index"><span itemprop="name">Spring</span></a>
                </span>
                  , 
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Spring/SpringSecurity/" itemprop="url" rel="index"><span itemprop="name">SpringSecurity</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="TodoItem"><a href="#TodoItem" class="headerlink" title="TodoItem"></a>TodoItem</h1><h2 id="OAuth2标准研究-todo"><a href="#OAuth2标准研究-todo" class="headerlink" title="OAuth2标准研究 todo"></a>OAuth2标准研究 todo</h2><h2 id="AuthorizationServerConfigurerAdapter-vsWebSecurityConfigurerAdapter-todo"><a href="#AuthorizationServerConfigurerAdapter-vsWebSecurityConfigurerAdapter-todo" class="headerlink" title="AuthorizationServerConfigurerAdapter vsWebSecurityConfigurerAdapter todo"></a>AuthorizationServerConfigurerAdapter vsWebSecurityConfigurerAdapter todo</h2><h2 id="判断是否超时的逻辑-todo"><a href="#判断是否超时的逻辑-todo" class="headerlink" title="判断是否超时的逻辑 todo"></a>判断是否超时的逻辑 todo</h2><h2 id="CORS-todo"><a href="#CORS-todo" class="headerlink" title="CORS todo"></a>CORS todo</h2><h2 id="JSR-250-todo"><a href="#JSR-250-todo" class="headerlink" title="JSR-250 todo"></a>JSR-250 todo</h2><h1 id="Basic-Knowledge"><a href="#Basic-Knowledge" class="headerlink" title="Basic Knowledge"></a>Basic Knowledge</h1><h2 id="很好的基础教程"><a href="#很好的基础教程" class="headerlink" title="很好的基础教程"></a>很好的基础教程</h2><p><a href="https://www.baeldung.com/security-spring" target="_blank" rel="noopener">Security with Spring</a></p>
<h2 id="token值在哪里生成？怎么生成？"><a href="#token值在哪里生成？怎么生成？" class="headerlink" title="token值在哪里生成？怎么生成？"></a>token值在哪里生成？怎么生成？</h2><p>默认鉴权生成token的url是”/oauth/token”，在TokenEndpoint里面生成。<br>SpringSecurity默认的token生成url是：<a href="http://hostname:port/oauth/token" target="_blank" rel="noopener">http://hostname:port/oauth/token</a><br>但是要进入到真正的TokenEndpoint里面还需要经过一道道关卡：<br>0 = {WebAsyncManagerIntegrationFilter@13114}<br>1 = {SecurityContextPersistenceFilter@13113}<br>2 = {HeaderWriterFilter@13112}<br>3 = {LogoutFilter@13111}<br>4 = {ClientCredentialsTokenEndpointFilter@13110}<br>5 = {BasicAuthenticationFilter@13108}<br>6 = {RequestCacheAwareFilter@13248}<br>7 = {SecurityContextHolderAwareRequestFilter@13247}<br>8 = {AnonymousAuthenticationFilter@13246}<br>9 = {SessionManagementFilter@13245}<br>10 = {ExceptionTranslationFilter@13244}<br>11 = {FilterSecurityInterceptor@13243} </p>
<p>0 = {OrderedGatewayFilter@13342} “OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter@25a2c4dc}, order=-2147483648}”<br>1 = {OrderedGatewayFilter@13343} “OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@62dfe152}, order=-2147482648}”<br>2 = {OrderedGatewayFilter@13344} “OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=me.fengorz.kiwi.gateway.filter.GenericRequestGlobalFilter@430f0c63}, order=-1000}”<br>3 = {OrderedGatewayFilter@13345} “OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@1e75af65}, order=-1}”<br>4 = {OrderedGatewayFilter@13346} “OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardPathFilter@2bee1c13}, order=0}”<br>5 = {OrderedGatewayFilter@13347} “OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.GatewayMetricsFilter@71098fb3}, order=0}”<br>6 = {OrderedGatewayFilter@13936} “OrderedGatewayFilter{delegate=me.fengorz.kiwi.gateway.filter.ValidateCodeGatewayFilter$$Lambda$854/120561697@1f06c463, order=1}”<br>7 = {OrderedGatewayFilter@14156} “OrderedGatewayFilter{delegate=me.fengorz.kiwi.gateway.filter.PasswordDecoderGatewayFilter$$Lambda$855/473170143@13f576a8, order=2}”<br>8 = {OrderedGatewayFilter@13349} “OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@29d81c22}, order=10000}”<br>9 = {OrderedGatewayFilter@13350} “OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@25a52a60}, order=10100}”<br>10 = {OrderedGatewayFilter@13351} “OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@1859b996}, order=2147483646}”<br>11 = {OrderedGatewayFilter@13352} “OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.NettyRoutingFilter@15549dd7}, order=2147483647}”<br>12 = {OrderedGatewayFilter@13353} “OrderedGatewayFilter{delegate=GatewayFilterAdapter{delegate=org.springframework.cloud.gateway.filter.ForwardRoutingFilter@18d396eb}, order=2147483647}”</p>
<p>最终默认情况下是通过DefaultTokenServices里面的createAccessToken方法调用到RedisTokenStore的storeAccessToken方法对token一系列的详细信息存储到redis里面。</p>
<h2 id="Spring-Security默认的过滤器栈"><a href="#Spring-Security默认的过滤器栈" class="headerlink" title="Spring Security默认的过滤器栈"></a>Spring Security默认的过滤器栈</h2><p>0 = {WebAsyncManagerIntegrationFilter@12983}<br>1 = {SecurityContextPersistenceFilter@12982}<br>2 = {HeaderWriterFilter@12981}<br>3 = {LogoutFilter@12980}<br>4 = {ClientCredentialsTokenEndpointFilter@12979}<br>5 = {BasicAuthenticationFilter@12977}<br>6 = {RequestCacheAwareFilter@13387}<br>7 = {SecurityContextHolderAwareRequestFilter@13386}<br>8 = {AnonymousAuthenticationFilter@13385}<br>9 = {SessionManagementFilter@13384}<br>10 = {ExceptionTranslationFilter@13383}<br>11 = {FilterSecurityInterceptor@13382} </p>
<h2 id="AuthorizationServerSecurityConfigurer"><a href="#AuthorizationServerSecurityConfigurer" class="headerlink" title="AuthorizationServerSecurityConfigurer"></a>AuthorizationServerSecurityConfigurer</h2><p>allowFormAuthenticationForClients()：<br>在BasicAuthenticationFilter之前添加clientCredentialsTokenEndpointFilter。</p>
<h1 id="Problem-Solution"><a href="#Problem-Solution" class="headerlink" title="Problem Solution"></a>Problem Solution</h1><h2 id="maven依赖出现了不同版本的TokenEndpoint"><a href="#maven依赖出现了不同版本的TokenEndpoint" class="headerlink" title="maven依赖出现了不同版本的TokenEndpoint"></a>maven依赖出现了不同版本的TokenEndpoint</h2><p>原因是Spring自己的依赖冲突了，在父工程根目录的dependencyManagement里面添加<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;!--稳定版本，替代spring security bom内置--&gt;</span><br><span class="line">&lt;dependency&gt;</span><br><span class="line">    &lt;groupId&gt;org.springframework.security.oauth&lt;/groupId&gt;</span><br><span class="line">    &lt;artifactId&gt;spring-security-oauth2&lt;/artifactId&gt;</span><br><span class="line">    &lt;version&gt;$&#123;security.oauth.version&#125;&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure></p>
<h2 id="权限校验的配置不能冲突"><a href="#权限校验的配置不能冲突" class="headerlink" title="权限校验的配置不能冲突"></a>权限校验的配置不能冲突</h2><p>比如我在某个配置类配置了：<br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/wH4Lai.png" alt><br>这样会导致全局的权限放开失效：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 直接放行URL</span><br><span class="line">ignore:</span><br><span class="line">  urls:</span><br><span class="line">    - /EnhancerTokenEndpoint/**</span><br></pre></td></tr></table></figure></p>
<p>全局的安全配置一般放在common-security模块：<br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/cTim2v.png" alt></p>
<h2 id="Spring-Security默认不会打印debug日志"><a href="#Spring-Security默认不会打印debug日志" class="headerlink" title="Spring Security默认不会打印debug日志"></a>Spring Security默认不会打印debug日志</h2><p>可通过配置类打开：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">@Override</span><br><span class="line">public void configure(WebSecurity web) throws Exception &#123;</span><br><span class="line">    web.debug(true);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>但是这种配置类打印的error日志不全，很多时候一些深层次的报错是不会打印出来的，因为：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">catch (AuthenticationException failed) &#123;</span><br><span class="line">	SecurityContextHolder.clearContext();</span><br><span class="line"></span><br><span class="line">	if (debug) &#123;</span><br><span class="line">		this.logger.debug(&quot;Authentication request for failed: &quot; + failed);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	this.rememberMeServices.loginFail(request, response);</span><br><span class="line"></span><br><span class="line">	onUnsuccessfulAuthentication(request, response, failed);</span><br><span class="line"></span><br><span class="line">	if (this.ignoreFailure) &#123;</span><br><span class="line">		chain.doFilter(request, response);</span><br><span class="line">	&#125;</span><br><span class="line">	else &#123;</span><br><span class="line">		this.authenticationEntryPoint.commence(request, response, failed);</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	return;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>类似这样的代码都有判断if(debug),这种事因为spring security默认用的是logback-classic，需要在classpath加上logback-spring.xml日志打印配置文件。</p>
<h2 id="通过postman调用接口token验证不通过"><a href="#通过postman调用接口token验证不通过" class="headerlink" title="通过postman调用接口token验证不通过"></a>通过postman调用接口token验证不通过</h2><p>我有二个微服务应用，一个是可以正常验证通过，另一个不能，这种问题只能跟源码分析了，最开始发现问题的端倪是：<br>接口请求之后，SpringSecurity会自动将严重的token转发给<a href="http://localhost:9991/auth/oauth/token在内部做验证，通过的话再继续走业务接口。" target="_blank" rel="noopener">http://localhost:9991/auth/oauth/token在内部做验证，通过的话再继续走业务接口。</a><br>在<a href="http://localhost:9991/auth/oauth/token验证接口需要经过一些列的过滤器，上面有提到。" target="_blank" rel="noopener">http://localhost:9991/auth/oauth/token验证接口需要经过一些列的过滤器，上面有提到。</a><br>在BasicAuthenticationFilter的doFilterInternal方法中对：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">String header = request.getHeader(&quot;Authorization&quot;);</span><br></pre></td></tr></table></figure></p>
<p>这个Authorization进行解密，异常的应用解密出来是：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">tokens = &#123;String[2]@15312&#125; </span><br><span class="line"> 0 = &quot;null&quot;</span><br><span class="line"> 1 = &quot;5951061b-856f-47cf-8f1b-dc34f975438c&quot;</span><br></pre></td></tr></table></figure></p>
<p>这里null就出现问题了，因为正常的那个不会是null，所以要研究一下转发到<a href="http://localhost:9991/auth/oauth/token之前塞进Header里面的Authorization是怎么来的？" target="_blank" rel="noopener">http://localhost:9991/auth/oauth/token之前塞进Header里面的Authorization是怎么来的？</a><br>于是只能先从SpringSecurity的过滤器栈中每个过滤器跟起，最终发现是在OAuth2AuthenticationProcessingFilter的doFilter方法的这一行：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Authentication authResult = authenticationManager.authenticate(authentication);</span><br></pre></td></tr></table></figure></p>
<p>发现了这里的authentication里面的getCredentials()返回是null，这才导致了上面转发到<a href="http://localhost:9991/auth/oauth/token验证token的时候出现0" target="_blank" rel="noopener">http://localhost:9991/auth/oauth/token验证token的时候出现0</a> = “null”，继续跟踪getCredentials()的来源，然后发现credentials是依赖于RemoteTokenServices的clientId属性，getPrincipal()依赖的是clientSecret属性，接着跟一下RemoteTokenServices是在哪里被注入到Spring的，发现其注入如下：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">         @Bean</span><br><span class="line">public RemoteTokenServices remoteTokenServices() &#123;</span><br><span class="line">	RemoteTokenServices services = new RemoteTokenServices();</span><br><span class="line">	services.setCheckTokenEndpointUrl(this.resource.getTokenInfoUri());</span><br><span class="line">	services.setClientId(this.resource.getClientId());</span><br><span class="line">	services.setClientSecret(this.resource.getClientSecret());</span><br><span class="line">	return services;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>this.resource，属性如下：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">@ConfigurationProperties(prefix = &quot;security.oauth2.resource&quot;)</span><br><span class="line">public class ResourceServerProperties implements BeanFactoryAware, InitializingBean &#123;</span><br><span class="line"></span><br><span class="line">	@JsonIgnore</span><br><span class="line">	private final String clientId;</span><br><span class="line"></span><br><span class="line">	@JsonIgnore</span><br><span class="line">	private final String clientSecret;</span><br><span class="line"></span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>这就和明确了，yml或者properties没有配置这二个对应的属性，于是配置上，这里采用了jasypt的加密方式：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">security:</span><br><span class="line">  oauth2:</span><br><span class="line">    client:</span><br><span class="line">      client-id: ENC(wORgugqWfXlIuzbal/3pjXTNXij/RSpo)</span><br><span class="line">      client-secret: ENC(rMd1buB3iI+si+W99eB+QFa3QburIEmY)</span><br><span class="line">      scope: server</span><br></pre></td></tr></table></figure></p>
<p>本来以为这个就正常了，结果报了新的错误：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Caused by: java.lang.IllegalArgumentException: Authorities must be either a String or a Collection</span><br></pre></td></tr></table></figure></p>
<p>debug了一下，发现上面的client-id和client-secret是注入成功的，那么异常应该是出现在其他地方，继续跟进。<br>最终发现，是在EnhancerUserAuthenticationConverter这个token认证转换器中的extractAuthentication方法报错，报错原因是因为admin用户没有赋权，在这段代码：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">private Collection&lt;? extends GrantedAuthority&gt; getAuthorities(Map&lt;String, ?&gt; map) &#123;</span><br><span class="line">    Object authorities = map.get(AUTHORITIES);</span><br><span class="line"></span><br><span class="line">    List&lt;String&gt; userNames = this.filterIgnorePropertiesConfig.getUserNames();</span><br><span class="line">    if (CollUtil.contains(userNames, map.get(SecurityConstants.DETAILS_USERNAME))) &#123;</span><br><span class="line">        authorities = CommonConstants.EMPTY;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    if (authorities instanceof String) &#123;</span><br><span class="line">        return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities);</span><br><span class="line">    &#125;</span><br><span class="line">    if (authorities instanceof Collection) &#123;</span><br><span class="line">        return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils</span><br><span class="line">                .collectionToCommaDelimitedString((Collection&lt;?&gt;) authorities));</span><br><span class="line">    &#125;</span><br><span class="line">    throw new IllegalArgumentException(&quot;Authorities must be either a String or a Collection&quot;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>这样如果直接写死代码忽略admin用户的话代码就太硬了，于是通过yml配置映射到配置独享filterIgnorePropertiesConfig，这样子比较灵活。</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-Hans">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2016/11/18/github-hexo-next-快速搭建偏亮的个人博客/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="Fengorz">
      <meta itemprop="description" content="A Quiet Departure.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Feng's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2016/11/18/github-hexo-next-快速搭建偏亮的个人博客/" class="post-title-link" itemprop="url">github+hexo+next 快速搭建漂亮的个人博客</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">Posted on</span>

              <time title="Created: 2016-11-18 13:59:05" itemprop="dateCreated datePublished" datetime="2016-11-18T13:59:05+08:00">2016-11-18</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">Edited on</span>
                <time title="Modified: 2020-07-21 14:08:24" itemprop="dateModified" datetime="2020-07-21T14:08:24+08:00">2020-07-21</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">In</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/blog-build/" itemprop="url" rel="index"><span itemprop="name">blog build</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <blockquote>
<p>本教程针对windows用户，苦逼实习生用不起mac</p>
</blockquote>
<h1 id="环境搭建"><a href="#环境搭建" class="headerlink" title="环境搭建"></a>环境搭建</h1><h3 id="安装git-for-windows"><a href="#安装git-for-windows" class="headerlink" title="安装git for windows"></a>安装git for windows</h3><p><a href="https://git-for-windows.github.io/" target="_blank" rel="noopener">《下载安装入口》</a><br>关于github与本地git客户端的关联这里不做阐述，百度一大把。</p>
<h3 id="安装node-js"><a href="#安装node-js" class="headerlink" title="安装node.js"></a>安装node.js</h3><p><a href="https://nodejs.org/en/download/" target="_blank" rel="noopener">《node.js下载安装入口》</a><br>官网下载速度可能会很慢，安装完毕之后可以再cmd窗口测试一下是否安装成功。<br>键入以下命令，你会看到对应的版本号。</p>
<pre><code>$ node -v
</code></pre><p>除此之外还要检测一下npm是否安装成功，npm作为node.js的子项目也被安装进去了，后面安装hexo需要依赖于npm，用下面命令测试，成功依然会返回版本号。</p>
<pre><code>$ npm -v
</code></pre><h4 id="安装hexo"><a href="#安装hexo" class="headerlink" title="安装hexo"></a>安装hexo</h4><p>在你想要安装hexo的目录里面右键Git Bash Here，然后键入以下命令。</p>
<pre><code>$ npm install -g hexo-cli
</code></pre><p>详情可以参照<a href="https://hexo.io/zh-cn/docs/index.html" target="_blank" rel="noopener">《hexo 中文文档入口》</a></p>
<h4 id="下载next主题"><a href="#下载next主题" class="headerlink" title="下载next主题"></a>下载next主题</h4><p>首先在你git bash窗口定位到安装hexo的根目录。</p>
<pre><code>$ cd your-hexo-site    
$ git clone https://github.com/iissnan/hexo-theme-next themes/next
</code></pre><p>详情请参照<a href="http://theme-next.iissnan.com/getting-started.html" target="_blank" rel="noopener">《hexo next主题中文配置教程入口》</a></p>
<h4 id="hexo-next配置"><a href="#hexo-next配置" class="headerlink" title="hexo next配置"></a>hexo next配置</h4><p>打开git bash，定位到你的hexo安装目录，执行</p>
<pre><code>$ hexo init
</code></pre><p>关于hexo的命令参照<a href="https://hexo.io/zh-cn/docs/commands.html" target="_blank" rel="noopener">《hexo 命令文档》</a><br>关于next第三方服务配置参照<a href="http://theme-next.iissnan.com/third-party-services.html" target="_blank" rel="noopener">《next第三方服务配置》</a></p>
<h1 id="编写博文"><a href="#编写博文" class="headerlink" title="编写博文"></a>编写博文</h1><p>hexo 支持使用常用的markdown语法，关于markdown的语法可以参照<a href="http://www.jianshu.com/p/075d7cac8fef" target="_blank" rel="noopener">《markdown新手教程》</a></p>
<blockquote>
<p>特别要注意的地方是，关于代码块网上很多都说得模棱两可，要实现上面代码高亮的代码块只要在代码上面空一行，前面键入大空格Tab开头就可以了，详细的markdown语法这里就不一一列出。</p>
</blockquote>
<p>博文的md文件写完之后保存，切回git bash窗口，重新生成静态文件</p>
<pre><code>$ hexo g
INFO  Start processing
INFO  Files loaded in 1.93 s
INFO  Generated: search.xml
INFO  Generated: 2016/11/18/github-hexo-next-快速搭建偏亮的个人博客/index.html
INFO  2 files generated in 874 ms
</code></pre><p>静态文件生成之后可以先部署到本地预览一下</p>
<pre><code>$ hexo s
INFO  Start processing
INFO  Hexo is running at http://localhost:4000/. Press Ctrl+C to stop.
</code></pre><p>效果满意的话就可以执行一下命令发布到github远程仓库，然后访问your_username.github.io。<br>ok，博客搭建完毕！</p>
<h2 id="全部md文件重新生成静态网页"><a href="#全部md文件重新生成静态网页" class="headerlink" title="全部md文件重新生成静态网页"></a>全部md文件重新生成静态网页</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo g -f</span><br></pre></td></tr></table></figure>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-Hans">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2019/10/15/Mac汇总/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="Fengorz">
      <meta itemprop="description" content="A Quiet Departure.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Feng's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2019/10/15/Mac汇总/" class="post-title-link" itemprop="url">Mac汇总</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">Posted on</span>

              <time title="Created: 2019-10-15 21:16:54" itemprop="dateCreated datePublished" datetime="2019-10-15T21:16:54+08:00">2019-10-15</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">Edited on</span>
                <time title="Modified: 2020-07-16 20:58:54" itemprop="dateModified" datetime="2020-07-16T20:58:54+08:00">2020-07-16</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">In</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Mac/" itemprop="url" rel="index"><span itemprop="name">Mac</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="Mac-Native-Function"><a href="#Mac-Native-Function" class="headerlink" title="Mac Native Function"></a>Mac Native Function</h1><h2 id="Mac-hotkey"><a href="#Mac-hotkey" class="headerlink" title="Mac hotkey"></a>Mac hotkey</h2><table>
<thead>
<tr>
<th>key</th>
<th>desc</th>
</tr>
</thead>
<tbody>
<tr>
<td>cmd + opt + esc</td>
<td>强制退出某个软件。通常在软件无响应时使用</td>
</tr>
<tr>
<td>cmd + shift+ 3</td>
<td>对整个屏幕进行截图</td>
</tr>
<tr>
<td>cmd + shift + 4</td>
<td>对自行选择的区域进行截图</td>
</tr>
<tr>
<td>cmd + shift + 5</td>
<td>更多方式截图和录屏（新版本系统）</td>
</tr>
<tr>
<td>cmd + `</td>
<td>切换同个软件的不同窗口</td>
</tr>
<tr>
<td>cmd + opt + 8</td>
<td>open or close zoom</td>
</tr>
<tr>
<td>cmd + opt + -</td>
<td>zoom in</td>
</tr>
<tr>
<td>cmd + opt + =</td>
<td>zoom out</td>
</tr>
<tr>
<td>opt + shift + 方向</td>
<td>先用触摸板选中一处，然后可以通过方向键叠加选中的内容</td>
</tr>
<tr>
<td>^ + A</td>
<td>行首</td>
</tr>
<tr>
<td>^ + E</td>
<td>行尾</td>
</tr>
</tbody>
</table>
<h2 id="MacOS"><a href="#MacOS" class="headerlink" title="MacOS"></a>MacOS</h2><p>非必要更新软件一定要在空闲时间更新，比如这个：<br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/TmZg0s.png" alt="macOS_img"><br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/yAU7qe.png" alt="macOS_img"></p>
<p>Dock的最佳位置是放在右边，并且隐藏起来，这样既有较大的屏幕可视区间，也不会经常因为移动鼠标到左边而误触，毕竟MacOS的窗口控制习惯是在左边。</p>
<h2 id="通过命令和粘贴文件"><a href="#通过命令和粘贴文件" class="headerlink" title="通过命令和粘贴文件"></a>通过命令和粘贴文件</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"># 将a.txt文件类容写入剪切板，相当于 cmd + C</span><br><span class="line">pbcopy &lt; blogpost.txt</span><br><span class="line">cat a.txt | pbcopy      </span><br><span class="line"># 将主目录的文件列表复制到剪贴板</span><br><span class="line">ls ~ | pbcopy      </span><br><span class="line"># 复制终端当前目录</span><br><span class="line">pwd | pbcopy</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 将刚刚存入剪切板的a.txt内容复制到终端，相当于 cmd + v</span><br><span class="line">pbpaste              </span><br><span class="line"># 追加内容到对应的文件</span><br><span class="line">pbpaste &gt;&gt; tasklist.txt</span><br></pre></td></tr></table></figure>
<h1 id="Alfred"><a href="#Alfred" class="headerlink" title="Alfred"></a>Alfred</h1><h2 id="Powerful-command"><a href="#Powerful-command" class="headerlink" title="Powerful command"></a>Powerful command</h2><p>command of close any app：quit<br>command of search anything in file: in<br>快速用类vim软件打开选中文件</p>
<h2 id="不搜索Parallels-Desktop的内容"><a href="#不搜索Parallels-Desktop的内容" class="headerlink" title="不搜索Parallels Desktop的内容"></a>不搜索Parallels Desktop的内容</h2><p>打开spotlight-&gt;private，将Applications(Parallels)添加进来</p>
<h2 id="有道词典的插件"><a href="#有道词典的插件" class="headerlink" title="有道词典的插件"></a>有道词典的插件</h2><p>通过yd 快捷翻译和查询，enter快捷复制结</p>
<h2 id="按右键有很多快捷操作"><a href="#按右键有很多快捷操作" class="headerlink" title="按右键有很多快捷操作"></a>按右键有很多快捷操作</h2><p>比如搜索某个目录<br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/PXiZrB.png" alt><br>然后按右键可以有很多快捷操作<br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/3Do9ZM.png" alt><br>然后可以选择open with，选择不同的软件打开，我喜欢用iterm打开，快捷操作。<br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/zpzWvn.png" alt></p>
<h1 id="brew"><a href="#brew" class="headerlink" title="brew"></a>brew</h1><h4 id="安装卸载"><a href="#安装卸载" class="headerlink" title="安装卸载"></a>安装卸载</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">brew --version 或者 brew -v 显示brew版本信息</span><br><span class="line">brew install &lt;formula&gt; 安装指定软件</span><br><span class="line">brew unistall &lt;formula 卸载指定软件</span><br><span class="line">brew list  显示所有的已安装的软件</span><br><span class="line">brew search text 搜索本地远程仓库的软件，已安装会显示绿色的勾</span><br><span class="line">brew search /text/ 使用正则表达式搜软件</span><br></pre></td></tr></table></figure>
<h4 id="升级"><a href="#升级" class="headerlink" title="升级"></a>升级</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">brew update 自动升级homebrew（从github下载最新版本）</span><br><span class="line">brew outdated 检测已经过时的软件</span><br><span class="line">brew upgrade  升级所有已过时的软件，即列出的以过时软件</span><br><span class="line">brew upgrade &lt;formula&gt;升级指定的软件</span><br><span class="line">brew pin &lt;formula&gt; 禁止指定软件升级</span><br><span class="line">brew unpin &lt;formula&gt; 解锁禁止升级</span><br><span class="line">brew upgrade --all 升级所有的软件包，包括未清理干净的旧版本的包</span><br></pre></td></tr></table></figure>
<h4 id="查询搜索"><a href="#查询搜索" class="headerlink" title="查询搜索"></a>查询搜索</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew search name</span><br></pre></td></tr></table></figure>
<h4 id="国内使用速度慢的解决方法"><a href="#国内使用速度慢的解决方法" class="headerlink" title="国内使用速度慢的解决方法"></a>国内使用速度慢的解决方法</h4><p><a href="https://mirrors.tuna.tsinghua.edu.cn/help/homebrew/" target="_blank" rel="noopener">使用清华大学镜像</a></p>
<h1 id="Others"><a href="#Others" class="headerlink" title="Others"></a>Others</h1><h2 id="Chrome"><a href="#Chrome" class="headerlink" title="Chrome"></a>Chrome</h2><p>刷新页面快捷键：cmd+R</p>
<h2 id="AppCleaner被锁住无法删除"><a href="#AppCleaner被锁住无法删除" class="headerlink" title="AppCleaner被锁住无法删除"></a>AppCleaner被锁住无法删除</h2><p>可能需要kill -9 掉正在运行的pid，然后切换AppClearner到Widgets，再切换回来Applications，就可以删除了。</p>
<h2 id="brew安装的骚气的命令"><a href="#brew安装的骚气的命令" class="headerlink" title="brew安装的骚气的命令"></a>brew安装的骚气的命令</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ccat # cat的升级版，自动字符高亮</span><br><span class="line">htop # top的升级版，展示界面更加高大上</span><br><span class="line">    点击不同的展示栏还可以排序，比如按照CPU占用排序或者按照RES（资源占用排序）等等</span><br><span class="line">tldr # 对展示的文档进行了简化，并展示了对应的例子</span><br></pre></td></tr></table></figure>
<h2 id="SlowQuitApps"><a href="#SlowQuitApps" class="headerlink" title="SlowQuitApps"></a>SlowQuitApps</h2><p>有时候会误按到cmd+Q，安装这个软件之后可以在误按的时候有个确认的操作，防止误触退出。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">brew tap dteoh/sqa</span><br><span class="line">brew cask install slowquitapps</span><br></pre></td></tr></table></figure></p>
<p>安装之后要在system setting给上权限，然后可以开启开机自动启动。</p>
<h2 id="安装sshpass"><a href="#安装sshpass" class="headerlink" title="安装sshpass"></a>安装sshpass</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">curl -O -L https://fossies.org/linux/privat/sshpass-1.06.tar.gz &amp;&amp; tar xvzf sshpass-1.06.tar.gz</span><br><span class="line"></span><br><span class="line">cd sshpass-1.06</span><br><span class="line"></span><br><span class="line">./configure</span><br><span class="line"></span><br><span class="line">sudo make install</span><br></pre></td></tr></table></figure>
<h2 id="uPic"><a href="#uPic" class="headerlink" title="uPic"></a>uPic</h2><p><a href="https://blog.svend.cc/upic/tutorials/github/" target="_blank" rel="noopener">uPic结合github做图床</a><br>github token如果忘记了，可以在github设置里面重新生成：<br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/ToYZBP.png" alt><br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/Vym2hq.png" alt></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-Hans">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2019/11/06/fastdfs/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="Fengorz">
      <meta itemprop="description" content="A Quiet Departure.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Feng's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2019/11/06/fastdfs/" class="post-title-link" itemprop="url">fastdfs</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">Posted on</span>

              <time title="Created: 2019-11-06 09:57:27" itemprop="dateCreated datePublished" datetime="2019-11-06T09:57:27+08:00">2019-11-06</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">Edited on</span>
                <time title="Modified: 2020-07-16 20:58:54" itemprop="dateModified" datetime="2020-07-16T20:58:54+08:00">2020-07-16</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">In</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/fastdfs/" itemprop="url" rel="index"><span itemprop="name">fastdfs</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <blockquote>
<p><a href="https://www.cnblogs.com/chiangchou/p/fastdfs.html" target="_blank" rel="noopener">https://www.cnblogs.com/chiangchou/p/fastdfs.html</a></p>
</blockquote>
<h2 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h2><p><a href="https://www.bbsmax.com/A/MAzAr2jRJ9/" target="_blank" rel="noopener">https://www.bbsmax.com/A/MAzAr2jRJ9/</a></p>
<h3 id="测试上传"><a href="#测试上传" class="headerlink" title="测试上传"></a>测试上传</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fdfs_test /etc/fdfs/client.conf upload test.tx</span><br></pre></td></tr></table></figure>
<h2 id="查看Storage和Tracker是否在通信"><a href="#查看Storage和Tracker是否在通信" class="headerlink" title="查看Storage和Tracker是否在通信"></a>查看Storage和Tracker是否在通信</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fdfs_monitor /etc/fdfs/storage.conf</span><br></pre></td></tr></table></figure>
<h2 id="查看Storage和Tracker是否状态都正常"><a href="#查看Storage和Tracker是否状态都正常" class="headerlink" title="查看Storage和Tracker是否状态都正常"></a>查看Storage和Tracker是否状态都正常</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">netstat -unltp|grep fdfs</span><br></pre></td></tr></table></figure>
<p>正常的话结果如下：<br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/Q53RzT.png" alt="image"><br>只要没有二个都出现那么可能是其中一个down掉了。</p>
<h2 id="Storage两种启动方式"><a href="#Storage两种启动方式" class="headerlink" title="Storage两种启动方式"></a>Storage两种启动方式</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">/etc/init.d/fdfs_storaged start</span><br><span class="line"></span><br><span class="line">service fdfs_storaged start</span><br></pre></td></tr></table></figure>
<h2 id="tracker-重启"><a href="#tracker-重启" class="headerlink" title="tracker 重启"></a>tracker 重启</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fdfs_trackerd fdfs_conf/tracker.conf</span><br></pre></td></tr></table></figure>
<h2 id="com-github-tobato-fastdfs-exception-FdfsConnectException-无法获取服务端连接资源：can’t-create-connection-to-172-26-64-218-23000"><a href="#com-github-tobato-fastdfs-exception-FdfsConnectException-无法获取服务端连接资源：can’t-create-connection-to-172-26-64-218-23000" class="headerlink" title="com.github.tobato.fastdfs.exception.FdfsConnectException: 无法获取服务端连接资源：can’t create connection to/172.26.64.218:23000"></a>com.github.tobato.fastdfs.exception.FdfsConnectException: 无法获取服务端连接资源：can’t create connection to/172.26.64.218:23000</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">查看启动日志，看看是否启动成功</span><br><span class="line">tail -n10 /home/xxx/xxx/logs/xxx.log</span><br></pre></td></tr></table></figure>
<h2 id="错误码：2，错误信息：找不到节点或文件"><a href="#错误码：2，错误信息：找不到节点或文件" class="headerlink" title="错误码：2，错误信息：找不到节点或文件"></a>错误码：2，错误信息：找不到节点或文件</h2><p><a href="https://blog.csdn.net/csp_6666/article/details/97912732" target="_blank" rel="noopener">https://blog.csdn.net/csp_6666/article/details/97912732</a></p>
<h2 id="season-fastdfs"><a href="#season-fastdfs" class="headerlink" title="season/fastdfs"></a>season/fastdfs</h2><p><a href="https://www.bbsmax.com/A/MAzAr2jRJ9/" target="_blank" rel="noopener">https://www.bbsmax.com/A/MAzAr2jRJ9/</a></p>
<ul>
<li>配置文件在/fdfs_conf/下面</li>
<li>重新拉去至少要更改storage节点的/fdfs_conf/storage.conf文件里面的tracker_server的ip</li>
<li>再分别启动一下tracker和storage，storage可能已经启动了提示端口占用<br>tracker启动：<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fdfs_trackered %FastDFS%/tracker.conf</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>看下storage是否有效<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fdfs_monitor /etc/fdfs/storage.conf</span><br></pre></td></tr></table></figure></p>
<p><strong><em>特别要注意IP地址要改成外网配置的地址</em></strong></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-Hans">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2019/11/22/显示器选购指南/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="Fengorz">
      <meta itemprop="description" content="A Quiet Departure.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Feng's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2019/11/22/显示器选购指南/" class="post-title-link" itemprop="url">显示器选购指南</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">Posted on</span>

              <time title="Created: 2019-11-22 03:00:18" itemprop="dateCreated datePublished" datetime="2019-11-22T03:00:18+08:00">2019-11-22</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">Edited on</span>
                <time title="Modified: 2020-07-16 20:58:54" itemprop="dateModified" datetime="2020-07-16T20:58:54+08:00">2020-07-16</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">In</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/显示器/" itemprop="url" rel="index"><span itemprop="name">显示器</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h1 id="LG27UK850体验总结"><a href="#LG27UK850体验总结" class="headerlink" title="LG27UK850体验总结"></a>LG27UK850体验总结</h1><pre><code>本来我都不想浪费时间来写下这个总结的，因为一贯都很懒，但是有个事情激发了我的动力，入手了LG27UK850之后，本来还想在微信群里面分享一波，那个微信群本来是三五个好友的撩骚群，但是在天朝特色的环境下，曾经最活跃的好群，慢慢的变成了各自炫耀自己仅有的一点点成绩的地方，在卑微的虚荣心驱使之下，影响到我们的独善其身，这也是我现在慢慢得想淡化静默一些群的原因。
在我分享了一张刚买的显示器照片之后，果然不出我的意料，有二个朋友回复的是，&quot;辣鸡，LG泛白严重&quot;，&quot;内心毫无波动&quot;等，诸如此类的回复。我在寻思，也许是多年的好友，才能够肆无忌惮的各种踩，也许是有好友出自内心的提醒，毕竟忠言逆耳利于行，而又或许，虚荣心在作祟？不过都无所谓，我将仔细分析一下我这次的体验，冷暖自知。
此外，我TM昨晚刚下单，今天中午就降价100块，狗东一定是在针对我。
</code></pre><p>先说明一下我为什么要买显示器以及选中了LG27UK850的原因：</p>
<ol>
<li>我是MBP18，MBP18四个Type-C都支持Thunderbolt3</li>
<li>我的扩展坞没有DP接口，只有一个HDMI1.4，1.4它不香了，无法支持4k/60Hz，所以如果我使用原有的扩展坞的话的话，那么买的显示器如果没有Type-C接口，将支持不了4k/60Hz，而我又测试了一下HDMI1.4，明显感觉掉帧和卡顿，又或者我需要买那种Type-C转DP的线。</li>
<li>同时这块显示器电源之后用Type-C来输入的话，可以给MBP反向充电</li>
<li>可以通过Type-C CtoC连接，这样一来就是基于DP来传输的，速率上杠杠的。</li>
<li>有了Type-C直连，我就可以减少有线的很多连接和转接头，有时候我比较喜欢简约美。</li>
<li>为什么我不选择戴尔U2718Q，网上对于戴尔显示器的显示效果确实好评声音高于LG，但是我对比了二款显示器，价位戴尔高几百块，当然这个不是重点，主要戴尔U2718Q没有Type-C口，而其他各种参数他们基本一致，抛开品控不说，苹果的显示器也都是和LG合作的，所以上车LG，我不是很方。</li>
<li>我是真的迫不及待想要体验用上大屏 or 双屏，这样会更好能够利用好我的时间，提交效率。</li>
<li>每天上班都是用MBP，十足十的低头族，加上经常看手机，脖子已经吃不消了，搞不好还容易驼背圆肩什么的，大屏显示器它势在必得！</li>
</ol>
<h1 id="弊端"><a href="#弊端" class="headerlink" title="弊端"></a>弊端</h1><ul>
<li>旋转屏幕之后不会自动感应旋转画面，需要在系统额外设置，之前我一直以为是会自动旋转画面的。</li>
<li>朋友说的泛白，肉眼看上去，确实没有MBP屏幕那样的恰到好处，加上我本身自己是高度近视，眼镜其实已经用了很久了，貌似是有点点泛白的感觉，但是不做设计，感觉我自己没有这方面的极致追求。</li>
<li>我看到网上有人说反向充电会充不满，但是我自己试了一个下午，一直都是100%，所以不存在这个问题。</li>
<li>LG原装里面送的Type-C线不是雷电3，我看没有雷电标记，也就是普通的Type-C先，郁闷。。。</li>
<li>睡眠之后通过鼠标or键盘重新唤醒，需要等好几秒，如果待机很久，比如一整个晚上，会出现无法唤醒，必须打开笔记本盖子，才能唤醒，这个应该是MBP彻底休眠了。。。</li>
<li>亮度已经调整为最低，但是实际上还是偏亮，需要辅助性软件或者对比度也调低，才能找到合适的亮度，可能我本人眼睛也不适合看亮的东西。</li>
</ul>
<h1 id="接口"><a href="#接口" class="headerlink" title="接口"></a>接口</h1><p>显示器传输接口DP、HDMI（1.0和2.0）、VGA（上古时代的产品）、DVI（也是时代的遗物）  </p>
<h2 id="DP"><a href="#DP" class="headerlink" title="DP"></a>DP</h2><p>DisplayPort接口</p>
<h2 id="HDMI"><a href="#HDMI" class="headerlink" title="HDMI"></a>HDMI</h2><p>HDMI现在最新版本已经是2.x了，只有2.0之后的版本才支持4k+60p，最新2.1版本支持 8K/60Hz、4K/120Hz 视频、Dynamic HDR（动态HDR，对于一些电影、游戏或图片的较灰暗的画面貌似有更好的纠正显示效果），将频宽大幅提升到 48Gbps。</p>
<h2 id="DP-VS-HDMI"><a href="#DP-VS-HDMI" class="headerlink" title="DP VS HDMI"></a>DP VS HDMI</h2><ul>
<li>DP的最新版本是1.4，发布于2016年3月，1.5版本迟迟没有发布</li>
<li>HDMI最新版本为2.1，发布于2017年11月<br>查看网上对于两者的比较，基本得出的结论大概是这样：<br>如果是电脑显示器，优先选择DP。HDMI主要是影音应用的，带宽不如DP。<br>如果论专业度，首选DP吧，虽然HDMI与DP都支持4K*2K，但DP的宽带会更高。<br>但是我个人一眼扫过去他们二者的数据比较，感觉单从数据来看，可能差不多已经是不相上下了。</li>
</ul>
<h2 id="Thunderbolt3"><a href="#Thunderbolt3" class="headerlink" title="Thunderbolt3"></a>Thunderbolt3</h2><p>雷电三的数据线都是带有雷电标记的，如：<br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/4AsmkY.png" alt="image"><br>MBP2018一共有四个Type-C接口，都是支持雷电3的</p>
<h2 id="Thunderbolt3、USB-3-1-Gen2、-Type-C的区别"><a href="#Thunderbolt3、USB-3-1-Gen2、-Type-C的区别" class="headerlink" title="Thunderbolt3、USB 3.1 Gen2、 Type-C的区别"></a>Thunderbolt3、USB 3.1 Gen2、 Type-C的区别</h2><p>想要弄清楚这两种电缆的区别，首先就需要先理清雷电3、USB 3.1、Type-C这三个名词的概念。其实，雷电3（Thunderbolt 3）和USB 3.1都是数据传输协议。<br>不同传输标准区别主要在于传输速率。拿USB 3.1来说，还分为USB 3.1 Gen1和USB 3.1 Gen2，USB 3.1 Gen1的最大传输速率为5Gb/s，USB3.1 Gen2最大传输速率为10Gb/s。<br>而Type-C则是一种接口规格，除此之外还有Type-A、Type-B等其他接口规格。<br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/OzaYIT.png" alt="image"><br>而用户容易把雷电3和USB Type-C搞混淆的原因之一，就是两种电缆均采用了Type-C接口规格，看起来几乎完全相同。现在为了更好的区分两者，苹果最新的雷电3数据线上都会带有雷电标志，所以很重要的区别是线本身的电缆不一样。<br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/9b8HMD.png" alt="image"><br>雷电3和USB Type-C虽然有相同的接口，却与不同的传输协议配对，分别是雷电3（Thunderbolt 3）和USB 3.1。<br>一些 Thunderbolt 3 连接线可以作为 USB 3.1 Type-C 连接线使用，但不是所有的线缆都可以。而 USB 3.1 Type-C 连接线，却永远无法当做 Thunderbolt 3 连接线使用，就算大家都是相同的 USB-C 接口也不行。同时，并不是所有的 USB Type-C 线缆都能胜任规范中的最高 100W 传输功率，无论是 Thunderbolt 3 还是 USB 3.1 Type-C 都不一定能够达到。</p>
<p>USB Type-C 接口其实本身并不支持视频输出，但是它拥有替代模式，通过转接到其他芯片上来实现不同功能，它实际使用的是DP标准的信号传输，好处是可以通过一根线解决显示器的画面输出和供电问题。</p>
<h2 id="为什么LG送的Type-C非雷电3可以做传输？"><a href="#为什么LG送的Type-C非雷电3可以做传输？" class="headerlink" title="为什么LG送的Type-C非雷电3可以做传输？"></a>为什么LG送的Type-C非雷电3可以做传输？</h2><p>我用自己MBP的电源充电线连接显示器，显示无信号连接，显然不起作用，但是用LG附带的Type-C线就可以，询问客户说是普通的线。<br>于是我搜了苹果原装雷电3数据线，TM要两百多，LG难怪不送雷电3的线，然后我发现了双Type-C原来还可以这么玩：<br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/X2FuqL.png" alt="image"><br>难怪显示器用Type-C的线能够给MBP反向充电。<br>翻了半天，没找到合理的科普，暂且搁置。</p>
<h1 id="坏点测试网站"><a href="#坏点测试网站" class="headerlink" title="坏点测试网站"></a>坏点测试网站</h1><p><a href="http://pingmu.zh-ang.com/" target="_blank" rel="noopener">http://pingmu.zh-ang.com/</a></p>
<h1 id="下面附上我的测试结果"><a href="#下面附上我的测试结果" class="headerlink" title="下面附上我的测试结果"></a>下面附上我的测试结果</h1><p><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/pLSliT.png" alt="image"><br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/LL5L5z.png" alt="image"><br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/lBaLO9.png" alt="image"><br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/8ZhCcI.png" alt="image"><br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/56Xsiu.png" alt="image"><br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/NrtREc.png" alt="image"><br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/l2YypC.png" alt="image"></p>
<blockquote>
<p>下面是一些显示器选购的参数</p>
</blockquote>
<h1 id="色域"><a href="#色域" class="headerlink" title="色域"></a>色域</h1><ul>
<li>sRGB</li>
<li>NTSC</li>
</ul>
<h1 id="色差"><a href="#色差" class="headerlink" title="色差"></a>色差</h1><h1 id="分辨率-尺寸"><a href="#分辨率-尺寸" class="headerlink" title="分辨率 尺寸"></a>分辨率 尺寸</h1><p><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/Jhr774.png" alt="image"><br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/UNfhPV.png" alt="image"></p>
<h1 id="刷新率-灰阶响应时间"><a href="#刷新率-灰阶响应时间" class="headerlink" title="刷新率 灰阶响应时间"></a>刷新率 灰阶响应时间</h1><p><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/aXNYhn.png" alt="image"></p>
<ul>
<li>IPS：漏光听说可能会比较严重</li>
<li>TN：色彩太差，尽量不考虑，</li>
</ul>
<h1 id="带鱼屏"><a href="#带鱼屏" class="headerlink" title="带鱼屏"></a>带鱼屏</h1><p><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/wbAnv9.png" alt="image"><br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/I7TEW7.png" alt="image"></p>
<h1 id="推荐"><a href="#推荐" class="headerlink" title="推荐"></a>推荐</h1><p><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/uw7LCF.png" alt="image"><br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/XepCvX.png" alt="image"><br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/YP7wN7.png" alt="image"><br><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/IYBayE.png" alt="image"></p>
<h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p><img src="https://cdn.jsdelivr.net/gh/coding-by-feng/oss@master/uPic/PDLjPX.png" alt="image"></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  


  
  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/page/10/"><i class="fa fa-angle-left" aria-label="Previous page"></i></a><a class="page-number" href="/">1</a><span class="space">&hellip;</span><a class="page-number" href="/page/10/">10</a><span class="page-number current">11</span><a class="page-number" href="/page/12/">12</a><span class="space">&hellip;</span><a class="page-number" href="/page/25/">25</a><a class="extend next" rel="next" href="/page/12/"><i class="fa fa-angle-right" aria-label="Next page"></i></a>
  </nav>



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          Table of Contents
        </li>
        <li class="sidebar-nav-overview">
          Overview
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">Fengorz</p>
  <div class="site-description" itemprop="description">A Quiet Departure.</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">125</span>
          <span class="site-state-item-name">posts</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">68</span>
        <span class="site-state-item-name">categories</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">87</span>
        <span class="site-state-item-name">tags</span></a>
      </div>
  </nav>
</div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Fengorz</span>
</div>
  <div class="powered-by">Powered by <a href="https://hexo.io" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.org" class="theme-link" rel="noopener" target="_blank">NexT.Gemini</a>
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>
<script src="/js/utils.js"></script><script src="/js/motion.js"></script>
<script src="/js/schemes/pisces.js"></script>
<script src="/js/next-boot.js"></script>



  















  

  

</body>
</html>
